import asyncio

import httpx
from loguru import logger

from ..agent import K2CIAgent


class SMP:
    def __init__(self, agent: K2CIAgent):
        self.agent = agent
        self.http_cli = httpx.AsyncClient(timeout=10)
        self._is_online: bool = False

    async def register(self) -> bool:
        if self._is_online:
            return True

        ret = False
        try:
            await self.try_update_ip4()
            logger.info(f"[K2CI] 本机信息：{self.agent.host_info}")
            rsp = await self.http_cli.post(
                f"http://{self.agent.cfg.smp_ip}:{self.agent.cfg.smp_port}{self.agent.cfg.smp_register_uri}",
                headers={"Content-Type": "application/json"},
                data=self.agent.host_info
            )
            code = await rsp.json()["code"]
            ret = code == 0
        except (BaseException, Exception) as e:
            import traceback
            logger.error(e)
        finally:
            if ret:
                self._is_online = True
                logger.info(f"[K2CI] SMP注册成功")
            else:
                logger.warning(f"[K2CI] SMP注册失败")
            return ret

    async def is_keep_alive(self) -> bool:
        ret = False
        try:
            rsp = await self.http_cli.post(
                f"http://{self.agent.cfg.smp_ip}:{self.agent.cfg.smp_port}{self.agent.cfg.smp_heartbeat_uri}",
                headers={"Content-Type": "application/json"},
                data={"mac": self.agent.ip4_info[self.agent.host_info["ip"]]}
            )
            code = await rsp.json()["code"]
            ret = code == 0
        except (BaseException, Exception) as e:
            import traceback
            logger.error(e)
        finally:
            if ret:
                logger.info(f"[K2CI] SMP心跳正常")
            else:
                self._is_online = False
                logger.warning(f"[K2CI] SMP心跳遗失")
            return ret

    @property
    def is_online(self):
        return self._is_online

    async def unregister(self):
        await self.http_cli.aclose()

    async def try_update_ip4(self):
        try:
            reader, writer = await asyncio.open_connection(self.agent.cfg.rabbit_mq_ip, self.agent.cfg.rabbit_port)
            sk = writer.transport.get_extra_info("socket")
            ip, port = sk.getsockname()
            self.agent.host_info["ip"] = ip
            self.agent.host_info["mac"] = self.agent.ip4_info["ip"]
            writer.close()
        except (BaseException, Exception):
            if self.agent.ip4_info:
                _ = list(self.agent.ip4_info.items())
                self.agent.host_info["ip"] = _[0][0]
                self.agent.host_info["mac"] = _[0][1]
